/*
 * PlayerService.java
 * classes : com.ns.liumeiti.PlayerService
 * @author 牛帅
 * V 1.0.0
 * Create at 2011-8-24 上午9:07:45
 */
package com.wzz.common.player;

import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;

import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;

import com.wzz.common.utils.LogUtil;
import com.wzz.common.utils.UIEvent;

/**
 *  牛帅
 *  此类应用的方法:
 *  1. isPlaying()方法是判断 当前播放状态的标记
 *  2. play() 播放的时候调用
 *  3. isPause() 暂停的标记
 *  4. pause() 暂停的时候被调用
 *  5. restart() 从新播放
 *  6. seekTo() 拖动进度的时候被调用
 *  7. onPrepared() 实现OnPreparedListener必须实现的方法 准备好了 开始播放
 *  8. onCompletion()播放完毕后回调的方法 要实现OnCompletionListener接口
 *  9. onError() 播放发生错误的方法  
 *  10. onBufferingUpdate() 缓冲进度变化的方法 要实现OnBufferingUpdateListener接口
 *  11. getDuration()获取当前时间的方法
 *  12. stop() 暂停方法
 *  
 */
public class PlayerService implements OnBufferingUpdateListener, OnErrorListener, OnCompletionListener,
    OnPreparedListener {

  private static final String TAG = "PlayerService";
  /** 单利的对象 */
  private static volatile PlayerService instance;
  /** MediaPlayer的对象 */
  private MediaPlayer mediaPlayer;
  private boolean isPause = false; // 暂停
  /** 歌曲播放完成 **/
  public static final int PALY_FINISH = 0x111;
  /** 缓冲进度变化 */
  public static final int BUFFERING_UPDATE = 0x112;
  /** 当前时间变化 */
  public static final int CURRENT_POSITION_CHANGE = 0x113;
  public Timer timer; // 时间变量
  /** TimerTask对象 */
  public static TimerTask listenCurrentPositionChange;
  /** 上一次推出是的时间 */
  private int lastTime;

  /**
   * 启动TimerTask 1秒换一次
   */
  public void startTimer() {
    timer.schedule(listenCurrentPositionChange, 0, 1000);
  }

  /**
   * 当前时间位置的变化(异步)
   */
  private void onCurrentPositionChange() {
    // 当前位置
    int position = mediaPlayer.getCurrentPosition();
    // 总的位置
    int duration = mediaPlayer.getDuration();

    if (duration > 0) {
      // 发消息 给 AudioPlayer
      UIEvent.getInstance().notifications(CURRENT_POSITION_CHANGE, position, duration);
    }
  }

  /**
   * 构造方法
   */
  private PlayerService() {
    if (mediaPlayer == null) {
      mediaPlayer = new MediaPlayer();
      // 设置mediaPlayer 的样式
      mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
      // 循环
      mediaPlayer.setLooping(false);
      // 各种监听
      mediaPlayer.setOnCompletionListener(this);
      mediaPlayer.setOnPreparedListener(this);
      mediaPlayer.setOnBufferingUpdateListener(this);
      mediaPlayer.setOnErrorListener(this);
      timer = new Timer();
      initTimer();
      startTimer();
    }
  }

  /**
   * 单例的方法 便于 其他类调用
   * 
   * @return
   */
  public static PlayerService getInstance() {
    if (instance == null) {
      synchronized (PlayerService.class) {
        if (instance == null) {
          instance = new PlayerService();
        }
      }
    }
    return instance;
  }

  /**
   * 初始化TimerTask
   */
  private void initTimer() {
    if (listenCurrentPositionChange == null) {
      listenCurrentPositionChange = new TimerTask() {
        @Override
        public void run() {
          if (mediaPlayer != null && mediaPlayer.isPlaying()) {
            // 调用异步执行时间变化
            onCurrentPositionChange();
          }
        }
      };
    }
  }
  public boolean isPlaying(){
    return mediaPlayer.isPlaying();
  }
  /**
   * 播放方法
   * 
   * @param url
   *          1.歌曲的url 2.上一次记录的时间
   * @param lastTime
   */
  public void play(String url, int lastTime) {
    LogUtil.d(TAG, "[B]play path is :" + url);
    // 保存本地的时间
    this.lastTime = lastTime;
    // 播放前从新设置
    mediaPlayer.reset();
    try {
      // 设置url的路劲
      mediaPlayer.setDataSource(url);
    } catch (IllegalArgumentException e1) {
      LogUtil.e(TAG, "1", e1);
    } catch (IllegalStateException e1) {
      LogUtil.e(TAG, "2", e1);
    } catch (IOException e1) {
      LogUtil.e(TAG, "3", e1);
    }
    try {
      mediaPlayer.prepare();
    } catch (IllegalStateException e) {
      LogUtil.e(TAG, "4", e);
    } catch (IOException e) {
      LogUtil.e(TAG, "5", e);
    }
  }

  /**
   * 暂停标记
   * 
   * @return
   */
  public boolean isPause() {
    return isPause;
  }

  /**
   * 暂停
   */
  public void pause() {
    mediaPlayer.pause();
    isPause = true;
  }
  /**
   * 从新开始
   */
  public void restart() {
    mediaPlayer.start();
    isPause = false;
  }
  /**
   * 移动拖动条
   * @param second
   */
  public void seekTo(int second) {
    mediaPlayer.seekTo(second);
  }

  /**
   * 
   * @param mp
   * @see android.media.MediaPlayer.OnPreparedListener#onPrepared(android.media.MediaPlayer)
   */
  @Override
  public void onPrepared(MediaPlayer mp) {
    LogUtil.d(TAG, "the url is ready , go start![onPrepared]");
    mediaPlayer.start();
    if (this.lastTime != 0) {
      LogUtil.d(TAG, "last time is {" + this.lastTime + "}");
      mediaPlayer.pause();
      mediaPlayer.seekTo(this.lastTime);
      mediaPlayer.start();
    }
    this.lastTime = 0;
  }

  /**
   * 
   * @param mp
   * @see android.media.MediaPlayer.OnCompletionListener#onCompletion(android.media.MediaPlayer)
   *      mp3播放完毕的时候调用 播放完毕后会发送一个播放完毕的消息
   */
  @Override
  public void onCompletion(MediaPlayer mp) {
    LogUtil.d(TAG, "播放完毕!!!!");
    UIEvent.getInstance().notifications(PALY_FINISH);
  }

  /**
   * 缓冲进度变化
   * 
   * @param mp
   * @param percent
   * @see android.media.MediaPlayer.OnBufferingUpdateListener#onBufferingUpdate(android.media.MediaPlayer,
   *      int)
   */
  @Override
  public void onBufferingUpdate(MediaPlayer mp, int percent) {
    UIEvent.getInstance().notifications(BUFFERING_UPDATE, percent, 0);
  }

  /**
   * MediaPlayer发生错误的时候调用
   * 
   * @param mp
   * @param what
   * @param extra
   * @return
   * @see android.media.MediaPlayer.OnErrorListener#onError(android.media.MediaPlayer,
   *      int, int)
   */
  @Override
  public boolean onError(MediaPlayer mp, int what, int extra) {
    LogUtil.d(TAG, "media player is error ! mp : [" + mp.toString() + "] what is :[" + what + "] extra is :[" + extra
        + "]");
    pause();
    return true;
  }

  /**
   * @return 获取当前时间
   */
  public int getDuration() {
    return mediaPlayer.getDuration();
  }

  /**
   * 暂停 销毁相关的对象
   */
  public void stop() {
    if (timer != null) {
      timer.cancel();
      timer = null;
    }
    if (listenCurrentPositionChange != null) {
      listenCurrentPositionChange.cancel();
      listenCurrentPositionChange = null;
    }
    mediaPlayer.release();
    mediaPlayer = null;
    instance = null;
  }
  
}